/*  File Name	: Table.h
 *  Author		: Javie Pong
 *	 E-mail		: 823960168@qq.com
 *  Created on	: 2012-8-5
 *  Description:
 */

#ifndef TABLE_H_
#define TABLE_H_
#include "Timer.h"
#include "EnginePlayer.h"
#include "Poker.h"
#include "ProcResult.h"

typedef std::vector<int> IntVector;
typedef std::vector<EnginePlayer*> PlayerVector;


struct TableBaseInfo
{
	TableBaseInfo()
	{
		reset();
	};
	void reset()
	{
		this->table_id = 0;
		this->cost =0;
		this->min_bet=0;
		this->min_chips_=0;
		this->max_chips_=0;
	}
	int table_id;//桌子id
	int cost;//每局扣除的费用
	int min_bet;//最小下注
	int min_chips_;//带入房间的最小筹码
	int max_chips_;//带入房间的最大筹码
};

struct ChipsPool
{
	ChipsPool()
	{
		total_chips =0;
		player_vec_.clear();
	}
	int total_chips;
	PlayerVector player_vec_;
};

typedef std::vector<ChipsPool> ChipsPoolVec;
typedef std::map<int,ProcResult> ResultMap;

class Table: virtual public Timer
{
public:
	Table(int p=0);
	virtual ~Table();

	virtual int handle_timeout(void);

	int init(EngineMonitor *monitor);
	int table_id(int id=0);

	EngineMonitor *monitor(void);

	const TableBaseInfo &base_info(void);
	void set_base_info(const TableBaseInfo &info);

	int start_timer(void);
	int stop_timer(void);

	int player_enter(EnginePlayer *player,int pos);
	int player_exit(EnginePlayer *player);

	int player_start(EnginePlayer *player);
	int bet(EnginePlayer *player);	//下注
	int raise(EnginePlayer *player);	//加赌注
	int all_in(EnginePlayer *player);	//全下
	int fold(EnginePlayer *player,bool force);	//弃牌
	int call(EnginePlayer *player);	//跟牌
	int check(EnginePlayer *player);	//过牌

	bool is_full(void);
	bool is_start(void);
	bool is_calculating(void);

	int min_chips(void);
	int min_bet(void);
	int player_count(void);
	int assign_pos(void);
	int cur_max_bet(void);

	int update_chips_record(int index,int value);
	int make_up_table_info(MessageBlock *mb,int start_index=0,bool with_card=false);
	int make_up_private_card_info(MessageBlock *mb);

	int broadcast_to_table(int cmd,MessageBlock *mb,int self_id=0,bool to_self=true);

	void reset(void);
private:
	int start_game(void);
	int prepare(void);
	int holecards(void);//底牌
	int pre_flop(void);//底牌权/前翻牌圈
	int flop(void);//翻牌 - 首三张公共牌
	int flop_round(void);//翻牌圈
	int turn(void);//转牌 - 第四张公共牌
	int turn_round(void);//转牌圈
	int river(void);//河牌 - 第五张公共牌
	int river_round(void);// 河牌圈
	int end_game(void);
	void clear(void);

	void broadcast_result(void);

	void to_shuffle(void);//洗牌
	int run_round(GameStep next_step);
	int to_deal(void);//发牌
	int to_cut(void);//切牌
	int dealer(void);//确定庄家和大小盲点

	int next_player_index(int cur_index);
	int make_pool(GameStep step);
	int notify_pool_info(GameStep step);

	bool check_start_condition(void);
	bool check_curr_player(void);

	bool is_fold(EnginePlayer *player);
	bool is_bet_end(int cur_index=0);


	static int cmp_result(ProcResult r1,ProcResult r2);
	static bool is_equal(ProcResult &r1,ProcResult &r2);
	static int cmp_chips(const int &v1,const int &v2);

	int wait_time(void);
	void update_max_bet(int value);

	void notify_operator(EnginePlayer *player,int time);
private:
	EngineMonitor *monitor_;
	TableBaseInfo base_info_;

	//PlayerMap player_map_;//玩家map
	PlayerVector player_vec_;//玩家位置vector
	int player_count_;//当前桌子人数

	bool is_wait_;//是否在等待玩家确认操作
	bool is_start_;//是否正在游戏中
	bool is_reset_dealer_;//是否重新确定庄家
	bool is_table_timer_start_;//定时器是否已经启动


	Poker poker_;//扑克牌
	IntVector left_pos_;//空座位
	int last_dealer_;//上一局的庄家
	GameStep game_step_;

	//////////////clear every time//////////////////
	int small_player_;//小盲位
	int large_player_;//大盲位
	int small_deal_;//小盲位玩家应下的最小赌注
	int cur_oper_player_;//当前轮到操作的玩家
	int last_oper_player_;
	int player_in_game_;//当局游戏的人数
	int player_gaming_;//当前仍继续游戏的人数（不包括all_in的玩家）

	bool is_calculating_;//正在计算结果
	bool prepare_wait_;//满足条件准备开始时等待

	Card* pub_card_[5];//公共牌
	int poker_index_;//当前扑克牌使用到的索引
	int cur_max_bet_;//当前下注最大值
	int total_chips_;//当前所有池筹码

	long notify_time_;

	ResultMap result_map_;
	ChipsPoolVec chips_pool_;
	IntVector all_in_chips_vec_;//全下的筹码值等级

	/*记录每个玩家的下注额
	（玩家在游戏进行时退出桌子的情况会找不到玩家数据）
	*/
	IntVector chips_record_vec_;
	RT_MUTEX rt_mutex_;
};

#endif /* TABLE_H_ */
